<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>大模型微调方法交互式可视化</title>
    <script src="https://cdn.tailwindcss.com"></script>
    <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
    <style>
        body {
            font-family: 'Inter', sans-serif; /* 应用 Inter 字体 */
            scroll-behavior: smooth; /* 平滑滚动 */
        }
        /* 导航栏悬停效果 */
        .nav-link:hover {
            background-color: #e0f2fe; /* light sky blue */
            color: #0c4a6e; /* dark sky blue */
        }
        /* 卡片悬停效果 */
        .interactive-card {
            transition: transform 0.3s ease, box-shadow 0.3s ease; /* 平滑过渡效果 */
        }
        .interactive-card:hover {
            transform: translateY(-5px); /* 向上移动 */
            box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05); /* 添加阴影 */
        }
        /* 激活状态的样式 */
        .active-tab {
            border-bottom: 2px solid #3b82f6; /* blue-500 */
            color: #3b82f6; /* blue-500 */
            font-weight: 600;
        }
        /* 隐藏元素 */
        .hidden {
            display: none;
        }
        /* 动画效果 */
        @keyframes fadeIn {
            from { opacity: 0; }
            to { opacity: 1; }
        }
        .fade-in {
            animation: fadeIn 0.5s ease-in-out;
        }
        /* LoRA 可视化样式 */
        .lora-vis {
            display: flex;
            align-items: center;
            justify-content: center;
            gap: 1rem; /* 元素间距 */
            margin-top: 1rem;
        }
        .lora-matrix {
            border: 2px solid;
            padding: 0.5rem;
            text-align: center;
            border-radius: 0.375rem; /* 圆角 */
        }
        .lora-arrow {
            font-size: 1.5rem; /* 箭头大小 */
            font-weight: bold;
        }
        /* RLHF 可视化样式 */
        .rlhf-step {
            border: 1px solid #e5e7eb; /* gray-200 */
            padding: 1rem;
            margin-bottom: 1rem;
            border-radius: 0.5rem; /* 圆角 */
            text-align: center;
        }
        .rlhf-arrow {
            font-size: 2rem; /* 箭头大小 */
            color: #9ca3af; /* gray-400 */
            margin: 0.5rem 0;
        }
        /* DeepSpeed ZeRO 可视化 */
        .zero-stage {
            border: 1px dashed #60a5fa; /* blue-400 */
            padding: 1rem;
            margin-top: 1rem;
            border-radius: 0.5rem; /* 圆角 */
            background-color: #eff6ff; /* blue-50 */
        }
        .gpu-box {
             background-color: #dbeafe; /* blue-100 */
             border: 1px solid #93c5fd; /* blue-300 */
             padding: 0.5rem;
             margin: 0.25rem;
             border-radius: 0.375rem; /* 圆角 */
             text-align: center;
             font-size: 0.875rem; /* 小字体 */
        }
        /* 侧边导航栏 */
        .sidebar {
            position: sticky; /* 固定位置 */
            top: 1rem; /* 距离顶部距离 */
            height: calc(100vh - 2rem); /* 高度为视口高度减去上下边距 */
            overflow-y: auto; /* 内容过多时显示滚动条 */
        }
        /* 响应式设计 */
        @media (max-width: 768px) {
            .sidebar {
                position: relative; /* 在小屏幕上取消固定 */
                height: auto;
                margin-bottom: 1rem;
            }
            /* 下面这几行可以被移除，因为 Tailwind 类名已经处理了 */
            /*
            .flex-col.md\:flex-row {
                 flex-direction: column;
            }
            .w-1/4 {
                width: 100%;
            }
            .w-3/4 {
                width: 100%;
            }
            */
        }
    </style>
</head>
<body class="bg-gray-50 text-gray-800 p-4 md:p-8">

    <div class="max-w-7xl mx-auto">
        <header class="mb-8 text-center">
            <h1 class="text-3xl md:text-4xl font-bold text-blue-600 mb-2">大模型微调方法交互式可视化</h1>
            <p class="text-lg text-gray-600">探索主流的大模型微调技术及其原理</p>
        </header>

        <div class="flex flex-col md:flex-row gap-8">
            <aside class="w-full md:w-1/4 sidebar pr-4">
                <h2 class="text-xl font-semibold mb-4 text-gray-700">导航</h2>
                <nav>
                    <ul class="space-y-2">
                        <li><a href="#overview" class="block px-4 py-2 rounded-md text-gray-700 nav-link">微调概述</a></li>
                        <li><a href="#directions" class="block px-4 py-2 rounded-md text-gray-700 nav-link">主流微调方向</a></li>
                        <li><a href="#peft" class="block px-4 py-2 rounded-md text-gray-700 nav-link">参数高效微调 (PEFT)</a></li>
                        <li><a href="#rlhf" class="block px-4 py-2 rounded-md text-gray-700 nav-link">强化学习微调</a></li>
                        <li><a href="#frameworks" class="block px-4 py-2 rounded-md text-gray-700 nav-link">主流微调框架</a></li>
                        <li><a href="#summary" class="block px-4 py-2 rounded-md text-gray-700 nav-link">总结与展望</a></li>
                    </ul>
                </nav>
            </aside>

            <main class="w-full md:w-3/4">
                <section id="overview" class="mb-12 p-6 bg-white rounded-lg shadow-md scroll-mt-16">
                    <h2 class="text-2xl font-semibold mb-4 text-blue-600 border-b pb-2">1. 大模型微调概述</h2>
                    <div class="space-y-4 text-gray-700">
                        <p><strong class="text-blue-500">什么是微调？</strong> 微调（Fine-tuning）是指在一个已经预训练好的大模型基础上，利用特定的、通常规模较小的数据集，对模型进行进一步训练，以适应特定任务或领域的过程。</p>
                        <p><strong class="text-blue-500">为什么需要微调？</strong>
                            <ul class="list-disc list-inside ml-4 space-y-1">
                                <li><strong class="font-medium">任务适配：</strong> 通用大模型虽然强大，但在特定任务上可能表现不够好，微调可以使其更专业。</li>
                                <li><strong class="font-medium">知识注入：</strong> 向模型注入特定领域（如医疗、法律、金融）的知识或私有数据。</li>
                                <li><strong class="font-medium">风格/行为对齐：</strong> 让模型的输出风格、语气或遵循的规则更符合特定要求（例如，扮演特定角色、遵循安全准则）。</li>
                                <li><strong class="font-medium">成本效益：</strong> 相比于从头训练一个大模型，微调所需的计算资源和数据量要少得多。</li>
                            </ul>
                        </p>
                        <p><strong class="text-blue-500">微调的必要性 (对比 RAG, Prompt Engineering, Agent):</strong></p>
                        <div class="bg-sky-50 p-4 rounded-md border border-sky-200">
                            <p>虽然 RAG (检索增强生成)、Prompt Engineering (提示工程) 和 Agent 技术可以在不改变模型参数的情况下提升模型在特定场景的表现，但它们各有侧重：</p>
                            <ul class="list-disc list-inside ml-4 space-y-1 mt-2">
                                <li><strong>Prompt Engineering:</strong> 优化输入提示词，引导模型产生期望输出，简单易行，但能力有限，难以改变模型的核心行为。</li>
                                <li><strong>RAG:</strong> 结合外部知识库进行检索，解决模型知识陈旧或缺乏特定知识的问题，适合需要实时或专业知识的问答场景。</li>
                                <li><strong>Agent:</strong> 赋予模型规划、使用工具和执行复杂任务的能力，更侧重于任务流程的自动化。</li>
                                <li><strong>微调:</strong> 直接修改模型参数，从根本上改变模型的知识和行为模式，适用于需要深度定制化模型能力的场景。</li>
                            </ul>
                            <p class="mt-2 font-medium">这些技术并非互斥，常常结合使用。例如，可以通过微调使模型更好地理解特定指令或遵循 RAG 的流程。</p>
                        </div>
                        <p><strong class="text-blue-500">企业应用前景：</strong> 微调使得企业能够利用大模型的基础能力，结合自身业务数据和需求，构建定制化的智能应用，如智能客服、代码生成、内容创作、数据分析等，是 AI 落地的重要途径。</p>
                    </div>
                </section>

                <section id="directions" class="mb-12 p-6 bg-white rounded-lg shadow-md scroll-mt-16">
                    <h2 class="text-2xl font-semibold mb-4 text-blue-600 border-b pb-2">2. 主流微调方向</h2>
                    <p class="mb-4 text-gray-700">根据修改模型参数的范围和方式，主流的微调方法可以分为以下三类：</p>
                    <div class="grid md:grid-cols-3 gap-6">
                        <div class="border p-4 rounded-lg bg-indigo-50 border-indigo-200 interactive-card">
                            <h3 class="text-lg font-semibold mb-2 text-indigo-700">a. 全量微调 (Full Fine-tuning)</h3>
                            <p class="text-sm text-gray-600 mb-2">更新模型的所有参数。</p>
                            <p class="text-sm"><strong class="font-medium">优点：</strong> 效果通常最好，模型能最大程度地适应新任务。</p>
                            <p class="text-sm"><strong class="font-medium">缺点：</strong> 计算成本高（需要大量 GPU 显存和时间），容易导致“灾难性遗忘”（模型忘记预训练中学到的通用知识），每个新任务都需要存储一份完整的模型副本。</p>
                            <div class="mt-3 text-center">
                                <svg class="w-16 h-16 mx-auto text-indigo-400" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 21V5a2 2 0 00-2-2H7a2 2 0 00-2 2v16m14 0h2m-2 0h-5m-9 0H3m2 0h5M9 7h6m-6 4h6m-6 4h6"></path></svg>
                                <p class="text-xs mt-1 text-indigo-600">所有层都参与训练</p>
                            </div>
                        </div>
                        <div class="border p-4 rounded-lg bg-teal-50 border-teal-200 interactive-card">
                            <h3 class="text-lg font-semibold mb-2 text-teal-700">b. 参数高效微调 (PEFT)</h3>
                            <p class="text-sm text-gray-600 mb-2">冻结大部分预训练模型参数，仅调整少量（或新增）参数。</p>
                            <p class="text-sm"><strong class="font-medium">优点：</strong> 计算成本低，训练速度快，显存占用少，不易发生灾难性遗忘，每个任务只需存储少量修改的参数。</p>
                            <p class="text-sm"><strong class="font-medium">缺点：</strong> 效果可能略逊于全量微调，需要选择合适的 PEFT 方法。</p>
                             <div class="mt-3 text-center">
                                <svg class="w-16 h-16 mx-auto text-teal-400" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6V4m0 2a2 2 0 100 4m0-4a2 2 0 110 4m-6 8a2 2 0 100-4m0 4a2 2 0 110-4m0 4v2m0-6V4m6 6v10m6-2a2 2 0 100-4m0 4a2 2 0 110-4m0 4v2m0-6V4"></path></svg>
                                <p class="text-xs mt-1 text-teal-600">仅调整部分参数</p>
                            </div>
                        </div>
                        <div class="border p-4 rounded-lg bg-amber-50 border-amber-200 interactive-card">
                            <h3 class="text-lg font-semibold mb-2 text-amber-700">c. 强化学习微调 (RLHF/RLAIF)</h3>
                            <p class="text-sm text-gray-600 mb-2">利用强化学习的方式，根据人类反馈（RLHF）或 AI 反馈（RLAIF）来优化模型，使其输出更符合人类偏好或特定标准（如无害性、有用性）。</p>
                            <p class="text-sm"><strong class="font-medium">优点：</strong> 能有效提升模型的对话质量、遵循指令能力和安全性。</p>
                            <p class="text-sm"><strong class="font-medium">缺点：</strong> 流程复杂，需要标注偏好数据或训练奖励模型，训练不稳定。</p>
                             <div class="mt-3 text-center">
                                <svg class="w-16 h-16 mx-auto text-amber-400" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14.828 14.828a4 4 0 01-5.656 0M9 10h.01M15 10h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path></svg>
                                <p class="text-xs mt-1 text-amber-600">基于反馈进行优化</p>
                            </div>
                        </div>
                    </div>
                </section>

                <section id="peft" class="mb-12 p-6 bg-white rounded-lg shadow-md scroll-mt-16">
                    <h2 class="text-2xl font-semibold mb-4 text-blue-600 border-b pb-2">3. 参数高效微调 (PEFT) 详解</h2>
                    <p class="mb-4 text-gray-700">PEFT 通过只调整模型的一小部分参数来显著降低微调成本。以下是几种主流的 PEFT 方法：</p>

                    <div class="mb-6 border-b border-gray-200">
                        <nav class="flex space-x-4" aria-label="Tabs">
                            <button onclick="showPeft('lora')" class="peft-tab active-tab py-2 px-4 text-center text-gray-500 hover:text-blue-600 focus:outline-none">LoRA</button>
                            <button onclick="showPeft('adapter')" class="peft-tab py-2 px-4 text-center text-gray-500 hover:text-blue-600 focus:outline-none">Adapter</button>
                            <button onclick="showPeft('prompt_tuning')" class="peft-tab py-2 px-4 text-center text-gray-500 hover:text-blue-600 focus:outline-none">Prompt Tuning</button>
                            <button onclick="showPeft('p_tuning')" class="peft-tab py-2 px-4 text-center text-gray-500 hover:text-blue-600 focus:outline-none">P-Tuning (v1/v2)</button>
                            <button onclick="showPeft('prefix_tuning')" class="peft-tab py-2 px-4 text-center text-gray-500 hover:text-blue-600 focus:outline-none">Prefix Tuning</button>
                        </nav>
                    </div>

                    <div id="peft-content" class="space-y-6">
                        <div id="peft-lora" class="peft-method fade-in">
                            <h3 class="text-xl font-semibold mb-2 text-teal-700">LoRA (Low-Rank Adaptation)</h3>
                            <p class="text-gray-700 mb-3">核心思想：大模型在微调过程中，其参数的改变量（ΔW）是低秩的。因此，可以用两个较小的低秩矩阵（A 和 B）的乘积来近似模拟这个改变量 (ΔW ≈ BA)。</p>
                            <p class="text-gray-700 mb-3">实现方式：冻结原始权重 W，在模型的某些层（通常是 Attention 层）旁边增加一个旁路，由两个低秩矩阵 A 和 B 组成。训练时只更新 A 和 B 的参数。推理时，可以将 BA 加回到原始权重 W 上 (W' = W + BA)，不增加额外的推理延迟。</p>
                            <p class="text-gray-700 mb-3"><strong class="font-medium">优点：</strong> 参数量极少（通常不到原模型的 0.1%），训练快，效果接近全量微调，易于部署和切换任务（只需替换 A 和 B）。</p>
                            <p class="text-gray-700"><strong class="font-medium">交互演示：</strong> 点击按钮模拟 LoRA 矩阵的引入和训练过程。</p>
                            <div class="mt-4 p-4 border rounded-lg bg-gray-50">
                                <p class="text-center font-medium mb-2">模型某一层 (如 Attention 的权重 W)</p>
                                <div class="flex justify-center items-center gap-4 mb-4">
                                    <div id="lora-original-w" class="lora-matrix border-gray-400 p-6 text-gray-600 transition-all duration-300">原始权重 W <br>(冻结)</div>
                                    <div id="lora-plus" class="lora-arrow hidden text-gray-500">+</div>
                                    <div id="lora-adapter" class="hidden flex flex-col items-center">
                                         <div class="flex items-center gap-2">
                                            <div id="lora-b" class="lora-matrix border-blue-500 text-blue-700 bg-blue-100">矩阵 B <br> (可训练)</div>
                                            <div class="lora-arrow text-blue-500">×</div>
                                            <div id="lora-a" class="lora-matrix border-blue-500 text-blue-700 bg-blue-100">矩阵 A <br> (可训练)</div>
                                         </div>
                                         <p class="text-xs text-blue-600 mt-1">低秩分解: ΔW ≈ BA</p>
                                    </div>
                                </div>
                                <div class="text-center">
                                    <button id="lora-toggle-btn" onclick="toggleLoRA()" class="bg-blue-500 hover:bg-blue-600 text-white font-medium py-2 px-4 rounded-lg transition-colors">
                                        引入 LoRA 旁路
                                    </button>
                                </div>
                                <p id="lora-status" class="text-center text-sm mt-3 text-gray-600">状态：仅使用原始权重 W。</p>
                            </div>
                        </div>

                        <div id="peft-adapter" class="peft-method hidden fade-in">
                            <h3 class="text-xl font-semibold mb-2 text-teal-700">Adapter Tuning</h3>
                            <p class="text-gray-700 mb-3">核心思想：在预训练模型的每一层（或某些层）中插入小的、称为 "Adapter" 的神经网络模块。训练时只更新 Adapter 模块的参数，而冻结原始模型的大部分参数。</p>
                            <p class="text-gray-700 mb-3">实现方式：Adapter 模块通常包含一个降维层（将高维特征映射到低维）、一个非线性激活函数和一个升维层（将低维特征映射回原始维度）。这种 "瓶颈" 结构限制了可训练参数的数量。</p>
                            <p class="text-gray-700 mb-3"><strong class="font-medium">优点：</strong> 参数效率高，易于实现，每个任务只需训练和存储小的 Adapter 模块。</p>
                            <p class="text-gray-700"><strong class="font-medium">缺点：</strong> 插入 Adapter 会增加模型的推理延迟。</p>
                             <div class="mt-4 p-4 border rounded-lg bg-gray-50 text-center">
                                <p class="font-medium mb-2">模型层结构示意</p>
                                <div class="flex items-center justify-center gap-2 text-sm">
                                    <div class="p-3 border rounded bg-gray-200 text-gray-700">...</div>
                                    <div class="p-3 border rounded bg-gray-200 text-gray-700">Transformer 层 N</div>
                                    <div class="text-2xl text-gray-400">→</div>
                                     <div class="p-2 border border-dashed border-teal-500 rounded bg-teal-100 text-teal-700">
                                        Adapter 模块<br>(降维->激活->升维)<br><strong class="text-xs">(可训练)</strong>
                                     </div>
                                     <div class="text-2xl text-gray-400">→</div>
                                    <div class="p-3 border rounded bg-gray-200 text-gray-700">Transformer 层 N+1</div>
                                    <div class="p-3 border rounded bg-gray-200 text-gray-700">...</div>
                                </div>
                                <p class="text-xs mt-2 text-gray-600">Adapter 模块被插入到原始模型层之间。</p>
                            </div>
                        </div>

                        <div id="peft-prompt_tuning" class="peft-method hidden fade-in">
                            <h3 class="text-xl font-semibold mb-2 text-teal-700">Prompt Tuning</h3>
                            <p class="text-gray-700 mb-3">核心思想：冻结整个预训练模型，只在输入端为每个任务学习一组小的、连续的向量（称为 "soft prompt" 或 "virtual tokens"），这些向量会拼接到原始的输入文本嵌入上。</p>
                            <p class="text-gray-700 mb-3">实现方式：将可训练的 virtual tokens 添加到输入序列的嵌入表示之前。模型在处理输入时，会像处理普通 token 一样处理这些 virtual tokens。</p>
                            <p class="text-gray-700 mb-3"><strong class="font-medium">优点：</strong> 参数量极少（比 LoRA 还少），存储和切换任务非常方便（只需存储 virtual tokens），不改变原始模型结构。</p>
                            <p class="text-gray-700"><strong class="font-medium">缺点：</strong> 效果可能不如 LoRA 或 Adapter 稳定，尤其是在较小的模型上或需要更复杂推理的任务上。</p>
                            <div class="mt-4 p-4 border rounded-lg bg-gray-50 text-center">
                                <p class="font-medium mb-2">输入嵌入示意</p>
                                <div class="flex items-center justify-center gap-2 text-sm flex-wrap">
                                    <div class="p-2 border border-dashed border-purple-500 rounded bg-purple-100 text-purple-700">
                                        Virtual Token 1<br><strong class="text-xs">(可训练)</strong>
                                    </div>
                                     <div class="p-2 border border-dashed border-purple-500 rounded bg-purple-100 text-purple-700">
                                        ...
                                    </div>
                                     <div class="p-2 border border-dashed border-purple-500 rounded bg-purple-100 text-purple-700">
                                        Virtual Token K<br><strong class="text-xs">(可训练)</strong>
                                    </div>
                                    <div class="p-2 border rounded bg-gray-200 text-gray-700">原始文本 Token 1</div>
                                     <div class="p-2 border rounded bg-gray-200 text-gray-700">...</div>
                                    <div class="p-2 border rounded bg-gray-200 text-gray-700">原始文本 Token N</div>
                                </div>
                                <p class="text-xs mt-2 text-gray-600">可训练的 Virtual Tokens 被添加到原始输入嵌入之前。</p>
                            </div>
                        </div>

                        <div id="peft-p_tuning" class="peft-method hidden fade-in">
                            <h3 class="text-xl font-semibold mb-2 text-teal-700">P-Tuning (v1 / v2)</h3>
                            <p class="text-gray-700 mb-3">P-Tuning 旨在改进 Prompt Tuning。</p>
                            <p class="text-gray-700 mb-3"><strong class="font-medium">P-Tuning v1:</strong> 类似于 Prompt Tuning，也学习 virtual tokens。但它使用一个小的 LSTM 网络（称为 prompt encoder）来生成这些 virtual tokens，并认为 token 之间存在依赖关系。同时，引入了一些 anchor tokens 来稳定训练。</p>
                            <p class="text-gray-700 mb-3"><strong class="font-medium">P-Tuning v2:</strong> 进一步改进，取消了 prompt encoder，直接将可训练的 virtual tokens 应用到模型的每一层（而不仅仅是输入层），使其更接近 Prefix Tuning。这使得 P-Tuning v2 在更广泛的任务和模型规模上表现更好，效果接近全量微调。</p>
                            <p class="text-gray-700 mb-3"><strong class="font-medium">优点 (v2):</strong> 效果好，参数量少，对不同任务和模型规模更鲁棒。</p>
                            <p class="text-gray-700"><strong class="font-medium">缺点 (v2):</strong> 比 Prompt Tuning 略复杂。</p>
                             <div class="mt-4 p-4 border rounded-lg bg-gray-50 text-center">
                                <p class="font-medium mb-2">P-Tuning v2 示意 (应用于多层)</p>
                                <div class="space-y-3">
                                    <div class="flex items-center justify-center gap-2 text-sm">
                                        <span class="font-medium">输入层:</span>
                                        <div class="p-2 border border-dashed border-orange-500 rounded bg-orange-100 text-orange-700">VT</div>
                                        <div class="p-2 border rounded bg-gray-200">Input</div>
                                    </div>
                                     <div class="flex items-center justify-center gap-2 text-sm">
                                        <span class="font-medium">中间层 N:</span>
                                        <div class="p-2 border border-dashed border-orange-500 rounded bg-orange-100 text-orange-700">VT</div>
                                        <div class="p-2 border rounded bg-gray-200">Hidden State</div>
                                    </div>
                                     <div class="flex items-center justify-center gap-2 text-sm">
                                        <span class="font-medium">中间层 N+1:</span>
                                         <div class="p-2 border border-dashed border-orange-500 rounded bg-orange-100 text-orange-700">VT</div>
                                        <div class="p-2 border rounded bg-gray-200">Hidden State</div>
                                    </div>
                                </div>
                                <p class="text-xs mt-2 text-gray-600">P-Tuning v2 将可训练的 Virtual Tokens (VT) 应用于模型的多个层。</p>
                                <p class="text-sm mt-3 text-gray-700"><strong class="font-medium">P-Tuning v2 的重要性：</strong> 随着模型规模的竞争趋于饱和，研究开始转向如何让更小的模型达到更好的性能（模型轻量化、专业化）。P-Tuning v2 在这方面表现出色，使得在中小规模模型上进行高效微调成为可能，是未来发展的重要方向。</p>
                            </div>
                        </div>

                         <div id="peft-prefix_tuning" class="peft-method hidden fade-in">
                            <h3 class="text-xl font-semibold mb-2 text-teal-700">Prefix Tuning</h3>
                            <p class="text-gray-700 mb-3">核心思想：类似于 Prompt Tuning，也是冻结原始模型参数。但它不是在输入嵌入层添加 virtual tokens，而是在 Transformer 的每一层的 Key 和 Value 向量之前添加一组可训练的 "prefix" 向量。</p>
                            <p class="text-gray-700 mb-3">实现方式：为每一层学习一组 prefix 向量 (P_k, P_v)，在计算 Attention 时，将它们拼接到原始的 Key 和 Value 序列之前。这样，模型在处理序列时可以关注到这些可训练的 prefix。</p>
                            <p class="text-gray-700 mb-3"><strong class="font-medium">优点：</strong> 参数量少，效果较好，尤其在生成任务上表现突出。</p>
                            <p class="text-gray-700"><strong class="font-medium">缺点：</strong> 实现比 Prompt Tuning 复杂，训练可能不如 LoRA 稳定。</p>
                            <div class="mt-4 p-4 border rounded-lg bg-gray-50 text-center">
                                <p class="font-medium mb-2">Attention K/V 计算示意 (某一层)</p>
                                <div class="space-y-2 text-sm">
                                    <div class="flex items-center justify-center gap-2">
                                        <span class="font-medium w-12">Key:</span>
                                        <div class="p-2 border border-dashed border-cyan-500 rounded bg-cyan-100 text-cyan-700">Prefix Pk <strong class="text-xs">(可训练)</strong></div>
                                        <div class="p-2 border rounded bg-gray-200 text-gray-700">Original Keys K</div>
                                    </div>
                                     <div class="flex items-center justify-center gap-2">
                                        <span class="font-medium w-12">Value:</span>
                                        <div class="p-2 border border-dashed border-cyan-500 rounded bg-cyan-100 text-cyan-700">Prefix Pv <strong class="text-xs">(可训练)</strong></div>
                                        <div class="p-2 border rounded bg-gray-200 text-gray-700">Original Values V</div>
                                    </div>
                                </div>
                                <p class="text-xs mt-2 text-gray-600">可训练的 Prefix 向量被添加到每一层 Attention 的 Key 和 Value 之前。</p>
                            </div>
                        </div>
                    </div>
                </section>

                <section id="rlhf" class="mb-12 p-6 bg-white rounded-lg shadow-md scroll-mt-16">
                    <h2 class="text-2xl font-semibold mb-4 text-blue-600 border-b pb-2">4. 强化学习微调 (RLHF / RLAIF)</h2>
                    <p class="text-gray-700 mb-4">RLHF (Reinforcement Learning from Human Feedback) 是一种利用人类偏好来优化模型输出的技术，常用于提升对话模型的安全性、有用性和指令遵循能力。RLAIF (Reinforcement Learning from AI Feedback) 则是用 AI 模型来代替人类进行反馈，以降低标注成本。</p>

                    <h3 class="text-lg font-semibold mb-3 text-amber-700">RLHF 主要流程：</h3>
                    <div class="flex flex-col items-center">
                        <div class="rlhf-step w-full md:w-3/4">
                            <span class="text-xs font-semibold inline-block py-1 px-2 uppercase rounded-full text-blue-600 bg-blue-200 mb-2">步骤 1</span>
                            <h4 class="font-medium mb-1">监督微调 (SFT)</h4>
                            <p class="text-sm text-gray-600">选择一个预训练模型，使用少量高质量的 "指令-回答" 数据对进行微调，让模型初步学会理解和执行指令。</p>
                            <p class="text-xs mt-1 text-gray-500">(可选，但通常推荐)</p>
                        </div>
                        <div class="rlhf-arrow">⬇️</div>

                        <div class="rlhf-step w-full md:w-3/4">
                             <span class="text-xs font-semibold inline-block py-1 px-2 uppercase rounded-full text-green-600 bg-green-200 mb-2">步骤 2</span>
                            <h4 class="font-medium mb-1">训练奖励模型 (RM)</h4>
                            <p class="text-sm text-gray-600">让 SFT 模型对一批 prompt 生成多个回答。人类标注者对这些回答进行排序（哪个更好？）。利用这些排序数据训练一个奖励模型 (RM)，RM 的目标是给好的回答打高分，给差的回答打低分。</p>
                             <p class="text-xs mt-1 text-gray-500">(核心步骤，需要人类标注)</p>
                        </div>
                         <div class="rlhf-arrow">⬇️</div>

                        <div class="rlhf-step w-full md:w-3/4">
                             <span class="text-xs font-semibold inline-block py-1 px-2 uppercase rounded-full text-purple-600 bg-purple-200 mb-2">步骤 3</span>
                            <h4 class="font-medium mb-1">强化学习优化 (如 PPO)</h4>
                            <p class="text-sm text-gray-600">将 SFT 模型作为策略 (Policy)，使用奖励模型 (RM) 作为环境的一部分。模型针对新的 prompt 生成回答，RM 对回答打分 (奖励)。使用强化学习算法 (如 PPO) 更新策略模型的参数，使其倾向于生成能获得更高奖励的回答。</p>
                            <p class="text-xs mt-1 text-gray-500">(优化模型以符合人类偏好)</p>
                        </div>
                    </div>
                     <p class="text-gray-700 mt-4"><strong class="font-medium">RLAIF:</strong> 主要区别在于步骤 2，使用另一个强大的 AI 模型（如 GPT-4）来代替人类标注者对回答进行排序或打分，从而训练奖励模型。</p>
                     <p class="text-gray-700 mt-2"><strong class="font-medium">PPO / DPO / KTO:</strong> 这些是用于 RL 优化步骤的具体算法。PPO (Proximal Policy Optimization) 是 RLHF 的经典算法。DPO (Direct Preference Optimization) 和 KTO (Kahneman-Tversky Optimization) 是更新的、更直接的方法，它们试图直接从偏好数据中优化模型，而无需显式训练奖励模型，通常更稳定、高效。</p>
                </section>

                <section id="frameworks" class="mb-12 p-6 bg-white rounded-lg shadow-md scroll-mt-16">
                    <h2 class="text-2xl font-semibold mb-4 text-blue-600 border-b pb-2">5. 主流微调框架</h2>
                    <p class="mb-4 text-gray-700">选择合适的微调框架可以极大简化开发流程。以下介绍两个主流的开源框架：DeepSpeed 和 Llama-Factory。</p>
                    <div class="grid md:grid-cols-2 gap-6">
                        <div class="border p-4 rounded-lg bg-red-50 border-red-200 interactive-card">
                            <h3 class="text-lg font-semibold mb-2 text-red-700">DeepSpeed</h3>
                             <p class="text-sm text-gray-600 mb-2">由微软开发，专注于大规模模型训练和推理的优化库。</p>
                            <p class="text-sm"><strong class="font-medium">核心特点：</strong>
                                <ul class="list-disc list-inside ml-4 text-sm space-y-1">
                                    <li><strong class="font-medium">ZeRO (零冗余优化器):</strong> 通过在多个 GPU 之间划分模型状态（优化器状态、梯度、模型参数），显著减少单个 GPU 的显存需求，实现更大模型的训练。</li>
                                    <li><strong class="font-medium">分布式训练支持:</strong> 提供高效的单机多卡和多机多卡训练方案。</li>
                                    <li><strong class="font-medium">混合精度训练:</strong> 支持 FP16/BF16，加速训练并减少显存。</li>
                                    <li><strong class="font-medium">卸载技术 (Offloading):</strong> 可以将部分模型状态卸载到 CPU 内存或 NVMe 存储，进一步降低 GPU 显存需求。</li>
                                </ul>
                            </p>
                            <p class="text-sm mt-2"><strong class="font-medium">适用场景：</strong> 训练非常大的模型（百亿、千亿参数级别），需要极致优化显存和计算效率，适合有一定分布式训练经验的开发者。</p>
                             <p class="text-sm mt-2"><strong class="font-medium">交互演示 (ZeRO):</strong> 点击查看不同 ZeRO Stage 的优化策略。</p>
                             <div class="mt-3 border-t pt-3">
                                 <div class="flex justify-around mb-2">
                                     <button onclick="showZeroStage(1)" class="zero-tab text-xs px-2 py-1 rounded bg-red-100 text-red-700 hover:bg-red-200" data-stage="1">ZeRO Stage 1</button>
                                     <button onclick="showZeroStage(2)" class="zero-tab text-xs px-2 py-1 rounded bg-gray-100 text-gray-700 hover:bg-gray-200" data-stage="2">ZeRO Stage 2</button>
                                     <button onclick="showZeroStage(3)" class="zero-tab text-xs px-2 py-1 rounded bg-gray-100 text-gray-700 hover:bg-gray-200" data-stage="3">ZeRO Stage 3</button>
                                 </div>
                                 <div id="zero-stage-details">
                                     <div id="zero-stage-1" class="zero-stage fade-in">
                                         <p class="font-medium text-sm text-red-800 mb-1">ZeRO Stage 1: 优化器状态分区</p>
                                         <p class="text-xs text-gray-600 mb-2">将优化器状态（如 Adam 的 momentum 和 variance）均匀分布到不同的 GPU 上。</p>
                                         <div class="flex flex-wrap justify-center">
                                             <div class="gpu-box">GPU 0<br>(Params, Grads, <strong class="text-red-600">Opt States 1/N</strong>)</div>
                                             <div class="gpu-box">GPU 1<br>(Params, Grads, <strong class="text-red-600">Opt States 2/N</strong>)</div>
                                             <div class="gpu-box">...</div>
                                             <div class="gpu-box">GPU N-1<br>(Params, Grads, <strong class="text-red-600">Opt States N/N</strong>)</div>
                                         </div>
                                         <p class="text-xs mt-1 text-gray-500">显著减少显存，对计算/通信影响较小。</p>
                                     </div>
                                      <div id="zero-stage-2" class="zero-stage hidden fade-in">
                                         <p class="font-medium text-sm text-red-800 mb-1">ZeRO Stage 2: 梯度分区</p>
                                         <p class="text-xs text-gray-600 mb-2">在 Stage 1 的基础上，进一步将梯度也分布到不同的 GPU 上。</p>
                                         <div class="flex flex-wrap justify-center">
                                             <div class="gpu-box">GPU 0<br>(Params, <strong class="text-red-600">Grads 1/N</strong>, <strong class="text-red-600">Opt States 1/N</strong>)</div>
                                             <div class="gpu-box">GPU 1<br>(Params, <strong class="text-red-600">Grads 2/N</strong>, <strong class="text-red-600">Opt States 2/N</strong>)</div>
                                             <div class="gpu-box">...</div>
                                             <div class="gpu-box">GPU N-1<br>(Params, <strong class="text-red-600">Grads N/N</strong>, <strong class="text-red-600">Opt States N/N</strong>)</div>
                                         </div>
                                          <p class="text-xs mt-1 text-gray-500">进一步减少显存，通信开销有所增加。</p>
                                     </div>
                                      <div id="zero-stage-3" class="zero-stage hidden fade-in">
                                         <p class="font-medium text-sm text-red-800 mb-1">ZeRO Stage 3: 模型参数分区</p>
                                         <p class="text-xs text-gray-600 mb-2">在 Stage 2 的基础上，将模型参数也分布到不同的 GPU 上。每个 GPU 只保留完整模型的一部分参数。</p>
                                          <div class="flex flex-wrap justify-center">
                                             <div class="gpu-box">GPU 0<br>(<strong class="text-red-600">Params 1/N</strong>, <strong class="text-red-600">Grads 1/N</strong>, <strong class="text-red-600">Opt States 1/N</strong>)</div>
                                             <div class="gpu-box">GPU 1<br>(<strong class="text-red-600">Params 2/N</strong>, <strong class="text-red-600">Grads 2/N</strong>, <strong class="text-red-600">Opt States 2/N</strong>)</div>
                                             <div class="gpu-box">...</div>
                                             <div class="gpu-box">GPU N-1<br>(<strong class="text-red-600">Params N/N</strong>, <strong class="text-red-600">Grads N/N</strong>, <strong class="text-red-600">Opt States N/N</strong>)</div>
                                         </div>
                                         <p class="text-xs mt-1 text-gray-500">最大限度减少显存，通信开销最大。适合训练超大模型。</p>
                                     </div>
                                 </div>
                             </div>
                        </div>
                        <div class="border p-4 rounded-lg bg-green-50 border-green-200 interactive-card">
                            <h3 class="text-lg font-semibold mb-2 text-green-700">LLaMA Factory</h3>
                             <p class="text-sm text-gray-600 mb-2">一个集成化、用户友好的大模型微调框架。</p>
                             <p class="text-sm"><strong class="font-medium">核心特点：</strong>
                                <ul class="list-disc list-inside ml-4 text-sm space-y-1">
                                    <li><strong class="font-medium">易用性:</strong> 提供 Web UI (LlamaBoard) 和命令行接口，无需编写复杂脚本即可配置和启动微调任务。</li>
                                    <li><strong class="font-medium">广泛支持:</strong> 支持多种主流 PEFT 方法 (LoRA, QLoRA, Adapter, Prompt Tuning 等) 和全量微调。</li>
                                    <li><strong class="font-medium">模型覆盖广:</strong> 支持 Llama、Mistral、Qwen、ChatGLM 等市面上绝大多数主流开源模型。</li>
                                    <li><strong class="font-medium">集成 DeepSpeed:</strong> 可以方便地勾选启用 DeepSpeed 的 ZeRO 优化。</li>
                                    <li><strong class="font-medium">预置数据集:</strong> 提供了一些常见任务的数据集和处理脚本。</li>
                                    <li><strong class="font-medium">社区活跃:</strong> 更新迭代快，遇到问题容易找到解决方案。</li>
                                </ul>
                            </p>
                             <p class="text-sm mt-2"><strong class="font-medium">适用场景：</strong> 新手入门，快速原型验证，中小型数据集微调，需要便捷地尝试不同模型和微调方法。</p>
                              <div class="mt-3 border-t pt-3 text-center">
                                 <img src="https://img.shields.io/github/stars/hiyouga/LLaMA-Factory?style=social" alt="LLaMA Factory Stars" class="mx-auto mb-2">
                                 <p class="text-xs text-gray-600">对新手友好，提供 Web UI 操作</p>
                                 <a href="https://github.com/hiyouga/LLaMA-Factory" target="_blank" class="text-sm text-blue-600 hover:underline mt-1 inline-block">访问 GitHub Repo</a>
                             </div>
                        </div>
                    </div>
                     <p class="text-gray-700 mt-6"><strong class="font-medium">总结对比：</strong> Llama-Factory 更像是一个集成了多种工具（包括 DeepSpeed 部分功能）的“瑞士军刀”，适合快速上手和实验；DeepSpeed 则更专注于底层性能优化，适合需要处理超大规模模型和追求极致效率的专业用户。对于初学者和大多数常规微调任务，Llama-Factory 是一个很好的起点。</p>
                </section>

                 <section id="summary" class="mb-12 p-6 bg-white rounded-lg shadow-md scroll-mt-16">
                    <h2 class="text-2xl font-semibold mb-4 text-blue-600 border-b pb-2">6. 总结与展望</h2>
                    <div class="space-y-4 text-gray-700">
                        <p><strong class="text-blue-500">本节回顾：</strong></p>
                        <ul class="list-disc list-inside ml-4 space-y-1">
                            <li>理解了微调的概念、必要性及其与 RAG、Prompt 等技术的区别。</li>
                            <li>掌握了三种主流微调方向：全量微调、参数高效微调 (PEFT) 和强化学习微调 (RLHF/RLAIF)。</li>
                            <li>详细了解了多种 PEFT 技术（Adapter, LoRA, Prompt Tuning, P-Tuning, Prefix Tuning）的原理和优缺点。</li>
                            <li>了解了 RLHF 的基本流程及其变种 RLAIF，以及 PPO/DPO 等优化算法。</li>
                            <li>对比了主流微调框架 DeepSpeed 和 Llama-Factory 的特点与适用场景。</li>
                        </ul>
                         <p><strong class="text-blue-500">关键要点：</strong></p>
                         <ul class="list-disc list-inside ml-4 space-y-1">
                             <li>优先选择<strong class="font-medium">主流</strong>微调方法和框架，便于获取社区支持和资源。</li>
                             <li><strong class="font-medium">PEFT</strong> 是当前兼顾效果和效率的主流选择，尤其是 LoRA 和 P-Tuning v2。</li>
                             <li><strong class="font-medium">RLHF/DPO</strong> 对于提升模型对齐性（安全性、有用性）至关重要。</li>
                              <li><strong class="font-medium">Llama-Factory</strong> 是新手友好的入门框架，<strong class="font-medium">DeepSpeed</strong> 适合大规模训练优化。</li>
                         </ul>
                        <p><strong class="text-blue-500">未来展望：</strong></p>
                        <ul class="list-disc list-inside ml-4 space-y-1">
                            <li><strong class="font-medium">模型轻量化与专业化：</strong> 随着大模型竞争加剧，如何在更小模型上通过高效微调（如 P-Tuning v2）达到优异性能，将是重要趋势。</li>
                            <li><strong class="font-medium">自动化与易用性：</strong> 微调框架将更加易用，出现更多自动化微调（AutoFT）工具，降低使用门槛。</li>
                            <li><strong class="font-medium">多模态微调：</strong> 对同时处理文本、图像、音频等多种模态的模型进行微调的需求将增加。</li>
                            <li><strong class="font-medium">数据质量与效率：</strong> 如何高效筛选和利用高质量数据进行微调，以及更高效的微调算法（如 DPO 的进一步发展）将是研究热点。</li>
                        </ul>
                        <p>掌握大模型微调技术，是把握 AI 时代机遇的关键一步。希望这个可视化演示能帮助您更好地理解这些主流方法。</p>
                    </div>
                </section>
            </main>
        </div>
    </div>

    <script>
        // PEFT 标签页切换功能
        function showPeft(methodId) {
            // 隐藏所有 PEFT 方法内容
            const methods = document.querySelectorAll('.peft-method');
            methods.forEach(method => {
                method.classList.add('hidden');
            });
            // 移除所有标签的激活状态
            const tabs = document.querySelectorAll('.peft-tab');
            tabs.forEach(tab => {
                tab.classList.remove('active-tab', 'text-blue-600', 'font-semibold');
                tab.classList.add('text-gray-500');
            });

            // 显示选定的 PEFT 方法内容
            const selectedMethod = document.getElementById('peft-' + methodId);
            if (selectedMethod) {
                selectedMethod.classList.remove('hidden');
                // 触发淡入效果 (可选)
                 selectedMethod.classList.remove('fade-in'); // 移除类以重新触发动画
                 void selectedMethod.offsetWidth; // 强制重绘
                 selectedMethod.classList.add('fade-in'); // 添加类
            }
            // 设置选定标签的激活状态
            const selectedTab = document.querySelector(`.peft-tab[onclick="showPeft('${methodId}')"]`);
            if (selectedTab) {
                selectedTab.classList.add('active-tab', 'text-blue-600', 'font-semibold');
                selectedTab.classList.remove('text-gray-500');
            }
        }

        // LoRA 交互功能
        let loraActivated = false;
        const loraOriginalW = document.getElementById('lora-original-w');
        const loraPlus = document.getElementById('lora-plus');
        const loraAdapter = document.getElementById('lora-adapter');
        const loraBtn = document.getElementById('lora-toggle-btn');
        const loraStatus = document.getElementById('lora-status');
        const loraB = document.getElementById('lora-b');
        const loraA = document.getElementById('lora-a');

        function toggleLoRA() {
            loraActivated = !loraActivated;
            if (loraActivated) {
                loraOriginalW.classList.add('p-4'); // 缩小一点
                loraOriginalW.classList.remove('p-6');
                loraPlus.classList.remove('hidden');
                loraAdapter.classList.remove('hidden');
                loraAdapter.classList.add('flex');
                loraBtn.textContent = '模拟训练完成 (移除旁路)';
                loraBtn.classList.remove('bg-blue-500', 'hover:bg-blue-600');
                loraBtn.classList.add('bg-green-500', 'hover:bg-green-600');
                loraStatus.textContent = '状态：引入 LoRA 旁路，仅训练矩阵 A 和 B。';
                loraStatus.classList.add('text-blue-700');
                loraStatus.classList.remove('text-gray-600');
                // 模拟训练效果 (可选)
                loraB.classList.add('animate-pulse');
                loraA.classList.add('animate-pulse');
                setTimeout(() => {
                    loraB.classList.remove('animate-pulse');
                    loraA.classList.remove('animate-pulse');
                }, 1500); // 动画持续1.5秒
            } else {
                loraOriginalW.classList.add('p-6');
                loraOriginalW.classList.remove('p-4');
                loraPlus.classList.add('hidden');
                loraAdapter.classList.add('hidden');
                loraAdapter.classList.remove('flex');
                loraBtn.textContent = '引入 LoRA 旁路';
                loraBtn.classList.remove('bg-green-500', 'hover:bg-green-600');
                loraBtn.classList.add('bg-blue-500', 'hover:bg-blue-600');
                loraStatus.textContent = '状态：训练完成，BA 合并回 W (W\' = W + BA)，旁路移除。';
                 loraStatus.classList.add('text-green-700');
                 loraStatus.classList.remove('text-blue-700','text-gray-600');

                 // 短暂显示合并效果
                 loraOriginalW.classList.add('bg-green-100', 'border-green-400');
                 setTimeout(() => {
                     loraOriginalW.classList.remove('bg-green-100', 'border-green-400');
                     loraStatus.textContent = '状态：仅使用原始权重 W。'; // 重置状态
                     loraStatus.classList.remove('text-green-700');
                     loraStatus.classList.add('text-gray-600');
                 }, 2000);
            }
        }

         // DeepSpeed ZeRO Stage 切换功能
        function showZeroStage(stage) {
            // 隐藏所有 Stage 内容
            const stages = document.querySelectorAll('.zero-stage');
            stages.forEach(s => s.classList.add('hidden'));
             // 移除所有 Tab 的激活样式
            const tabs = document.querySelectorAll('.zero-tab');
            tabs.forEach(t => {
                t.classList.remove('bg-red-100', 'text-red-700');
                t.classList.add('bg-gray-100', 'text-gray-700', 'hover:bg-gray-200');
            });

            // 显示选定的 Stage 内容
            const selectedStage = document.getElementById(`zero-stage-${stage}`);
            if (selectedStage) {
                selectedStage.classList.remove('hidden');
                // 触发淡入效果
                selectedStage.classList.remove('fade-in');
                void selectedStage.offsetWidth;
                selectedStage.classList.add('fade-in');
            }

             // 设置选定 Tab 的激活样式
            const selectedTab = document.querySelector(`.zero-tab[data-stage="${stage}"]`);
             if (selectedTab) {
                selectedTab.classList.remove('bg-gray-100', 'text-gray-700', 'hover:bg-gray-200');
                selectedTab.classList.add('bg-red-100', 'text-red-700');
            }
        }

        // 页面加载时默认显示 LoRA 和 ZeRO Stage 1
        document.addEventListener('DOMContentLoaded', () => {
            showPeft('lora');
            showZeroStage(1); // 确保默认显示 Stage 1
        });

    </script>
</body>
</html>
